#include "mythread.h"
#include "myproc.h"
#include "main.h"

pthread_t ttyS0RxThread;
pthread_t ttyS0RxThreadID;
pthread_t ttyS0TxThread;
pthread_t ttyS0TxThreadID;

pthread_t ttyS1RxThread;
pthread_t ttyS1RxThreadID;

pthread_t ttyUSBRxThread;
pthread_t ttyUSBRxThreadID;

pthread_t USBHIDRxThread;
pthread_t USBHIDRxThreadID;

void *TTYS1RxThreadProcess(void *msg)  //子线程，接收收银机过来的小票数据
{
    MSG *pmsg = (MSG*)msg;
    
    if((pmsg->fd) <0)
    {
        printf("%s: %d=>err: fd value has invalid\n", __FILE__, __LINE__);
        return 0;
    }
   // printf("ttyS1 child thread running...\n");
    uint8_t ttyBitDat = 0;
    uint16_t ttyDatCount = 0;
    uint8_t stepStatus = 0;
    int8_t readFlag = 0;
    while(1)
    {
        if(ttyDatCount >=TTYS1RXBUFFSIZE) 
        {
            stepStatus = 0; //超出缓冲区
            printf("%s:%d ttyDatCount point overflow from aobo dev!\n", __func__, __LINE__);
            break;
        }
        switch(stepStatus)
        {
            case 0: //初始化变量
                memset(pttyS1RxBuff, 0, TTYS1RXBUFFSIZE);
                ttyDatCount = 0;
                ttyBitDat = 0;
                readFlag = 0;
                stepStatus = 1; 
                break;
            
            case 1://开始接收数据
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {//接收数据出错，read函数返回错误，直接重置，重新等待数据开始
                    printf("Read error! ttyS1\n");
                    printf("Notice: checksum error data from main AOBO.\n");
                    stepStatus = 0;
                    break;
                }
     
                *(pttyS1RxBuff+ttyDatCount) = ttyBitDat;
                if(ttyDatCount >= 2) //收到3个字符以上
                {
                   if((*(pttyS1RxBuff+ttyDatCount) == 0x0A) && (*(pttyS1RxBuff+ttyDatCount-1) == 0x0A) && (*(pttyS1RxBuff+ttyDatCount-2) == 0x0A)) 
                   { //接收到前三个字符为0x0a 0x0a 0x0a，重置，重新开始接收
                        stepStatus =2;
                        break;
                   }
                }
                ttyDatCount++;     
                break;
            case 2: //数据接收结束后处理
                stepStatus = 0;
                pmsg->len = ttyDatCount;
                time_t tim;
                struct tm *tm;
                struct timeval tv;
                // CP pttyS1RxBuff的数据到 pmsg->buff
                for(uint16_t ii=0; ii<pmsg->len; ii++)
                {
                    pmsg->buff[ii] = *(pttyS1RxBuff+ii);
                }
                if(IsReturnBill(pttyS1RxBuff) == 1) //数据是退货单
                {
                    tim = time(NULL);
                    tm = localtime(&tim);
                    gettimeofday(&tv, NULL);
                    printf("[%02d:%02d:%02d.%03ld] linux ------- aobo [bill type: RETURN]\n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000);
                    break;
                }
                else
                {
                    tim = time(NULL);
                    tm = localtime(&tim);
                    gettimeofday(&tv, NULL);
                    printf("[%02d:%02d:%02d.%03ld] linux ------- aobo [bill type: NORMAL]\n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000);
                }
                memset(pBillinfo, 0, sizeof(BILLINFO)); //更新数据前清空billinfo结构体数据
                pBillinfo->totalItem = GetBillEan13Code(pttyS1RxBuff, pBillinfo);
                pBillinfo->totalPrice = GetBillTotalPrice(pttyS1RxBuff);
                //extern YANINFO (*pyaninfo)[];             
                //打印小票内容，勿删此代码
                tim = time(NULL);
                tm = localtime(&tim);
                gettimeofday(&tv, NULL);                 
                printf("[%02d:%02d:%02d.%03ld] linux <<<<<-- aobo [data rx len: %d bytes]\n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000,ttyDatCount);
                gettimeofday(&tv, NULL);
                printf("[%02d:%02d:%02d.%03ld] linux -->>>>> mapai [Transfer Start........]\n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000);
                uint16_t machItem =  MatchEAN13CODE(pBillinfo, pyaninfo); //匹配条码，并向码牌机传输数据
                gettimeofday(&tv, NULL);
                printf("[%02d:%02d:%02d.%03ld] linux ------- mapai [Transfer Terminal.]\n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000);
                printf("\t\t%-s\n", "Bill Content");
                printf("%-s\n", "+=======+=======+=======+=======+=======+=======+=======+");
                printf("%-14s\t%-s%-11d\t\t\t\t%s\n", "| Total Item:", "| ", pBillinfo->totalItem, "|");
                printf("%-14s\t%-s%-8.2f\t\t\t\t%s\n", "| Total Price:", "| ", pBillinfo->totalPrice, "|");
                printf("%-14s\t%-s%-11d\t\t\t\t%s\n", "| Match Item:", "| ", machItem, "|");
                printf("%-14s\t%-s%-11d\t\t\t\t%s\n", "| RX bytes:", "| ", ttyDatCount, "|");
                printf("%-s\n", "+=======+=======+=======+=======+=======+=======+=======+");
                for(uint16_t ii=0; ii<pBillinfo->totalItem; ii++)
                 {
                    printf("%-s%-2d\t%-s%-2d\t%-s%-7.2f\t%s\n", "| SerialNum: ", pBillinfo->itemInfo[ii].serialNum, "Quantity: ", pBillinfo->itemInfo[ii].quantity, "Subtotal: ", pBillinfo->itemInfo[ii].subTotal, "|");
	                printf("%-s%-13s\t\t\t\t%s\n", "| EAN13Code: ", pBillinfo->itemInfo[ii].ean13Code, "|");
	                printf("%-s\n", "+-------+-------+-------+-------+-------+-------+-------+");
                 }
                //打印代码结束
                break;
            
            default:
                stepStatus = 0;
                break;

        }
    } // while end
    return msg;
}

void *TTYS0RxThreadProcess(void *msg) //子线程，接码牌机过来数据
{
   
    MSG *pmsg = (MSG*)msg;
    if((pmsg->fd) <0)
    {
        printf("%s: %d=>err: fd value has invalid\n", __FILE__, __LINE__);
        return 0;
    }
    uint8_t ttyBitDat = 0;
    uint16_t ttyDatCount = 0;
    uint8_t stepStatus = 0;
    int8_t readFlag = 0;
    uint16_t maxDatLen = 6; //记录不同命令模式下数据的长度，默认最小长度，6个字节
    signal(SIGALRM, SigAlarmProcess);
    while(1)
    {
    
       if(ttyDatCount >=TTYS0RXBUFFSIZE) 
        {
            stepStatus = 0; //超出缓冲区
            printf("%s:%d ttyDatCount point overflow from mapai dev!\n", __func__, __LINE__);
            break;
        }
       switch (stepStatus) //状态机
       {
            case 0x00: //初始化变量
                memset(pttyS0RxBuff, 0, TTYS0RXBUFFSIZE);
                ttyDatCount = 0;
                maxDatLen = 0;
                stepStatus = 1;               
                break;

            case 0x01: //接收到0x02,表示数据开始
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {//接收数据出错，read函数返回错误，直接重置，重新等待数据开始
                    stepStatus = 0;
                    break;
                }
                if(ttyBitDat == 0x02) 
                {
                    stepStatus = 2; 
                    *(pttyS0RxBuff+ttyDatCount) = ttyBitDat;
                    ttyDatCount++;
                }
                break;
            
            case 0x02: //接收总长数据
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {
                    stepStatus = 0;
                    break;
                }
                *(pttyS0RxBuff+ttyDatCount) = ttyBitDat;
                ttyDatCount++;
                if(ttyDatCount >3)
                {
                    maxDatLen = (uint16_t)*(pttyS0RxBuff+1);
                    maxDatLen <<= 8;
                    maxDatLen |= (uint16_t)*(pttyS0RxBuff+2);
                    stepStatus = 0x03;
                }
                break;

            case 0x03://按数据包中接收到指定长度的数据后，进入下一步接收校验位
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {
                    stepStatus = 0;
                    break;
                }
                *(pttyS0RxBuff+ttyDatCount) = ttyBitDat;
                ttyDatCount++;
                if(ttyDatCount > maxDatLen+0x03)  stepStatus = 0x04; // +3 补齐数据字节总长度(开始符1字节+数据长度2字节
                break;

            case 0x04: //接收校验位
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {
                    stepStatus = 0;
                    break;
                }
                *(pttyS0RxBuff+ttyDatCount) = ttyBitDat;
                stepStatus = 0x05;
                break;

            case 0x05: //对数据进行校验，解析数据
                uint8_t checksum = 0;
                for(uint16_t ii=0; ii<ttyDatCount; ii++)
                { //计算除校验位以外的数据进行异或
                    checksum ^= *(pttyS0RxBuff+ii);
                }
                checksum ^= 0x02; //码牌端发过来的数据

                if(checksum == *(pttyS0RxBuff+ttyDatCount)) 
                {
                    //数据校验正确
                    stepStatus = 0x00;
                    pmsg->len = ttyDatCount+1;
                    // CP pttyS0RxBuff的数据到 pmsg->buff
                    for(uint16_t ii=0; ii<pmsg->len; ii++)
                    {
                        pmsg->buff[ii] = *(pttyS0RxBuff+ttyDatCount);
                    }
                    AnalysisMAPAICommand(pttyS0RxBuff); 
                   //打印接收到的数据
                    time_t tim = time(NULL);
                    struct tm *tm = localtime(&tim);
                    struct timeval tv;
                    gettimeofday(&tv, NULL);
                    //数据输出
                    if(mapaiCommand.mode == 0x1a)
                    {
                        printf("[%02d:%02d:%02d.%03ld] linux <<<<<-- mapai [DevInfo, len: %d bytes] ",\
                    tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000, ttyDatCount+1);
                    }
                    if(mapaiCommand.mode == 0x16)
                    {
                        printf("[%02d:%02d:%02d.%03ld] linux <<<<<-- mapai [Tick, len: %d bytes] ",\
                    tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000, ttyDatCount+1);
                    }
                    if(mapaiCommand.mode == 0x1c)
                    {
                        printf("[%02d:%02d:%02d.%03ld] linux <<<<<-- mapai [Reset, len: %d bytes] ",\
                    tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000, ttyDatCount+1);
                    }
                    for(int kk=0; kk<ttyDatCount+1; kk++)
                    {
                        printf("%02x ", *(pttyS0RxBuff+kk));
                    }
                    printf("\n");


                   ////////////////
                   if(sem_trywait(&transferStartFlag) == 0)
                   {
                        sem_post(&transferAllowFlag);//信号+1                             
                   }
                    alarm(0); //收到主机回复，取消alarm信号
                    switch(mapaiCommand.mode)
                    {
                        case 0x1A: //上电获取版本信息
                            GenerateVersionMsg(&ttyS0_verMSG);                       
                            TTYtransferDat(&ttyS0_verMSG); 
                                             
                            break;
                        
                        case 0x1C: //初始化工作\发送按键响应信息
                            GenerateInitMsg(&ttyS0_initMSG);
                            TTYtransferDat(&ttyS0_initMSG);                            
                            break;
                        
                        case 0x16: //巡问
                            GeneratePeriodResponseMsg(&ttyS0_ackMSG); //生成数据
                            TTYtransferDat(&ttyS0_ackMSG);
                            alarm(5); //5秒后，对respondMSGFlag进行判断，是否间巡依然存在
                            break;

                        default:
                            printf("Unknow Command! Not Processed! len: %d bytes. ", ttyDatCount+1);
                            for(int kk=0; kk<ttyDatCount+1; kk++)
                            {
                                printf("%02x ", *(pttyS0RxBuff+kk));
                            }
                            printf("\n");
                            break;
                    }
                //处理结束
                }else
                {
                    //数据校验不正确
                     printf("Notice: checksum error. data come from mapai.\n");
                     stepStatus = 0x00; //
                }
                break;

            default:
                stepStatus = 0x00;
                break;
       }
    }
    return msg;
}

//ttyS0发送数据线程
void *TTYS0TxThreadProcess(void *msg)
{
    pthread_detach(pthread_self());
    MSG *pmsg = (MSG*)msg;
    if((pmsg->fd) < 0) 
    {
        printf("%s:%d  has a error fd val!\n", __FILE__, __LINE__);
        
        pthread_exit(NULL);
    }
    uint16_t txStatus = write(pmsg->fd, pmsg->buff, pmsg->len);
    if(txStatus < 0) 
    {
        printf("err: TX thread write funcation has a error!\n");
    }
    //测试数据分析结果
    time_t tim = time(NULL);
    struct tm *tm = localtime(&tim);
    struct timeval tv;
    gettimeofday(&tv, NULL);
    //数据输出
    if(*((pmsg->buff)+0) == 0x06) //回复码牌
    {
        if(*((pmsg->buff)+5) == 0x1A)
        {
            printf("[%02d:%02d:%02d.%03ld] linux -->>>>> mapai [DevInfo, len: %d bytes] ",tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000, txStatus);
        }
        if(*((pmsg->buff)+5) == 0x1c)
        {
            printf("[%02d:%02d:%02d.%03ld] linux -->>>>> mapai [Reset, len: %d bytes] ",tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000, txStatus);
        }
        if(*((pmsg->buff)+5) == 0x16)
        {
            printf("[%02d:%02d:%02d.%03ld] linux -->>>>> mapai [Tick, len: %d bytes] ",tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000, txStatus);
        }
    }
    if(*((pmsg->buff)+0) == 0x02) 
        {
            if(*((pmsg->buff)+4) == 0xA3)
            {
                printf("[%02d:%02d:%02d.%03ld] linux -->>>>> mapai [Key, len: %d bytes] ",tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000, txStatus);
            }
        }
    for(int kk=0; kk<pmsg->len; kk++) //打印整个数据HEX
    {
        printf("%02x ", pmsg->buff[kk]);
    }
    printf("\n");
    //结束 
    pthread_exit(msg);
}

//TTY串口创建新线程发送
void TTYtransferDat(void *msg)
{
    pthread_t threadTxID;
    if( pthread_create(&threadTxID, NULL, TTYS0TxThreadProcess, msg) !=0 )
    {
        printf("Create ttyS0 TX thread failse!\n");
        return;
    } 
}

//子线程，接键盘过来的数据
void *TTYUSBRxThreadProcess(void *msg) 
{
   
    MSG *pmsg = (MSG*)msg;
    if((pmsg->fd) <0)
    {
        printf("%s: %d=>err: fd value has invalid\n", __FILE__, __LINE__);
        return 0;
    }
    uint8_t ttyBitDat = 0;
    uint16_t ttyDatCount = 0;
    uint8_t stepStatus = 0;
    int8_t readFlag = 0;
    uint16_t maxDatLen = 6; //记录不同命令模式下数据的长度，默认最小长度，6个字节

    while(1)
    {
       if(ttyDatCount >=TTYUSBRXBUFFSIZE) 
        {
            stepStatus = 0; //超出缓冲区
            printf("%s:%d ttyDatCount point overflow!\n", __func__, __LINE__);
            break;
        }
       switch (stepStatus) //状态机
       {
            case 0x00: //初始化变量
                memset(pttyUSBRxBuff, 0, TTYUSBRXBUFFSIZE);
                ttyDatCount = 0;
                maxDatLen = 0;
                stepStatus = 1;               
                break;

            case 0x01: //接收到0x02,表示数据开始
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {//接收数据出错，read函数返回错误，直接重置，重新等待数据开始
                    stepStatus = 0;
                    break;
                }
                if(ttyBitDat == 0x02) 
                {
                    stepStatus = 2; 
                    *(pttyUSBRxBuff+ttyDatCount) = ttyBitDat;
                    ttyDatCount++;
                }
                break;
            
            case 0x02: //接收总长数据
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {
                    stepStatus = 0;
                    break;
                }
                *(pttyUSBRxBuff+ttyDatCount) = ttyBitDat;
                ttyDatCount++;
                if(ttyDatCount >3)
                {
                    maxDatLen = (uint16_t)*(pttyUSBRxBuff+1);
                    maxDatLen <<= 8;
                    maxDatLen |= (uint16_t)*(pttyUSBRxBuff+2);
                    stepStatus = 0x03;
                }
                break;

            case 0x03://按数据包中接收到指定长度的数据后，进入下一步接收校验位
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {
                    stepStatus = 0;
                    break;
                }
                *(pttyUSBRxBuff+ttyDatCount) = ttyBitDat;
                ttyDatCount++;
                if(ttyDatCount > maxDatLen+0x03)  stepStatus = 0x04; // +3 补齐数据字节总长度(开始符1字节+数据长度2字节
                break;

            case 0x04: //接收校验位
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {
                    stepStatus = 0;
                    break;
                }
                *(pttyUSBRxBuff+ttyDatCount) = ttyBitDat;
                stepStatus = 0x05;
                break;

            case 0x05: //对数据进行校验，解析数据
                uint8_t checksum = 0;
                for(uint16_t ii=0; ii<ttyDatCount; ii++)
                { //计算除校验位以外的数据进行异或
                    checksum ^= *(pttyUSBRxBuff+ii);
                }
                checksum ^= 0x02; //码牌端发过来的数据

                if(checksum == *(pttyUSBRxBuff+ttyDatCount)) 
                {
                    //数据校验正确
                    pmsg->len = ttyDatCount+1;
                    // CP pttyUSBRxBuff的数据到 pmsg->buff
                    for(uint16_t ii=0; ii<pmsg->len; ii++)
                    {
                        pmsg->buff[ii] = *(pttyUSBRxBuff+ii);
                    }
                    AnalysisKEYBOARDCommand(pttyUSBRxBuff); //解析数据结构
                    //测试数据分析结果
                    time_t tim = time(NULL);
                    struct tm *tm = localtime(&tim);
                    struct timeval tv;
                    gettimeofday(&tv, NULL);   
                    printf("[%02d:%02d:%02d.%03ld] linux <<<<<-- KeyBoard [Key, len: %d] ",\
                    tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000, ttyDatCount+1);
                    for(int kk=0; kk<ttyDatCount+1; kk++)
                    {
                        printf("%02x ", *(pttyUSBRxBuff+kk));
                    }
                    printf("\n");


                    if(keyCommand.dat[4] == 0x01)  //小键盘有键按下
                    {
                        GenerateKeyPressMsg(&ttyS0_copy, keyCommand.dat[5]); //keyCommand.dat[5]键值
                        TTYtransferDat(&ttyS0_copy);
                    }
                    if(keyCommand.dat[4] == 0x00) //按键释放
                    {
                        GenerateKeyReleaseMsg(&ttyS0_copy, keyCommand.dat[5]);
                        TTYtransferDat(&ttyS0_copy);
                        if(keyCommand.dat[5] == KEY_MEMBER) //如果是会员键
                        {
                            SetMemberOrderForward();
                            TransferMembers(&USBHIDdat_MSG, GetMemberOrder());
                            
                        }
                        if(keyCommand.dat[5] == KEY_WORK) //如果是交班键
                        {
                            SetMemberOrderBack();
                            TransferMembers(&USBHIDdat_MSG, GetMemberOrder());
                        }

                    }
                    //添加打印信息
                    stepStatus = 0x00;
                }else
                {
                    //数据校验不正确
                     printf("Notice: checksum error. data come from keyboard.\n");
                     stepStatus = 0x00; //
                }
                break;

            default:
                stepStatus = 0x00;
                break;
       }
    }
  return msg;
}


void SigAlarmProcess(int sig)
{
    
    time_t tim = time(NULL);
    struct tm *tm = localtime(&tim);
    struct timeval tv;
    gettimeofday(&tv, NULL);   
    printf("[%02d:%02d:%02d.%03ld] linux -->>>>> mapai [loss tick signal. Relay device infomation, Relay member message thought USB HID]\n",\
    tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000);
    TTYtransferDat(&ttyS0_verMSG); //回复超时后，发送生成的版本信息
    TransferMembers(&USBHIDdat_MSG, GetMemberOrder());
    gettimeofday(&tv, NULL);   
    printf("[%02d:%02d:%02d.%03ld] linux ------- mapai [alive msg was transfered, chekc log and confirm mapai dev is online or offline]\n",\
    tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000);
    //alarm(4);
}


//USB HID发送线程处理函数
void *USBHIDTxThreadProcess(void *msg)
{
    pthread_detach(pthread_self());
    MSG *pmsg = (MSG*)msg;
    if((pmsg->fd) < 0) 
    {
        printf("%s:%d  has a error fd val!\n", __FILE__, __LINE__);
        
        pthread_exit(NULL);
    }
    uint16_t txStatus = write(pmsg->fd, pmsg->buff, pmsg->len);
    if(txStatus < 0) 
    {
        printf("err: USB HID TX thread write funcation has a error!\n");
    }
    //测试数据分析结果
    time_t tim = time(NULL);
    struct tm *tm = localtime(&tim);
    struct timeval tv;
    gettimeofday(&tv, NULL);
    //数据输出
    printf("[%02d:%02d:%02d.%03ld] linux -->>>>> CH9329 [USB HID, %d bytes] ",tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000, txStatus);
    for(int kk=0; kk<pmsg->len; kk++)
    {
        printf("%02x ", pmsg->buff[kk]);
    }
    printf("\n");
    //结束 
    pthread_exit(msg);
}

//USB创建新线程发送
void USBHIDtransferDat(void *msg)
{
    pthread_t threadTxID;
    if( pthread_create(&threadTxID, NULL, USBHIDTxThreadProcess, msg) !=0 )
    {
        printf("Create USB HID TX thread failse!\n");
        return;
    }

}

//子线程，接USB HID模块过来的数据
void *USBHIDRxThreadProcess(void *msg) 
{
   
    MSG *pmsg = (MSG*)msg;
    if((pmsg->fd) <0)
    {
        printf("%s: %d=>err: fd value has invalid\n", __FILE__, __LINE__);
        return 0;
    }
    uint8_t ttyBitDat = 0;
    uint16_t ttyDatCount = 0;
    uint8_t stepStatus = 0;
    int8_t readFlag = 0;
    uint8_t maxDatLen = 0; //记录不同命令模式下数据的长度，默认最小长度，0个字节

    while(1)
    {
       if(ttyDatCount >=USBHIDBUFFSIZE) 
        {
            stepStatus = 0; //超出缓冲区
            printf("%s:%d ttyDatCount point overflow!\n", __func__, __LINE__);
            break;
        }
       switch (stepStatus) //状态机
       {
            case 0: //初始化变量
                memset(pttyUSBHIDRxBuff, 0, USBHIDBUFFSIZE);
                ttyDatCount = 0;
                maxDatLen = 0;
                stepStatus = 1;               
                break;

            case 1: //接收到0x57,表示数据HEAD1
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {//接收数据出错，read函数返回错误，直接重置，重新等待数据开始
                    stepStatus = 0;
                    break;
                }
                if(ttyBitDat == 0x57)   
                {
                    stepStatus = 2; 
                    *(pttyUSBHIDRxBuff+ttyDatCount) = ttyBitDat;
                    ttyDatCount++;
                }
                break;
            
            case 2://接收到0xAB,表示数据开始
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {//接收数据出错，read函数返回错误，直接重置，重新等待数据开始
                    stepStatus = 0;
                    break;
                }
                if(ttyBitDat == 0xAB) 
                {
                    stepStatus = 3; 
                    *(pttyUSBHIDRxBuff+ttyDatCount) = ttyBitDat;
                    ttyDatCount++;
                }

            case 3: //接收地址码
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {//接收数据出错，read函数返回错误，直接重置，重新等待数据开始
                    stepStatus = 0;
                    break;
                }           
                stepStatus = 4; 
                *(pttyUSBHIDRxBuff+ttyDatCount) = ttyBitDat;
                ttyDatCount++;
                break;

            case 4: //接收命令码
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {//接收数据出错，read函数返回错误，直接重置，重新等待数据开始
                    stepStatus = 0;
                    break;
                }           
                stepStatus = 5; 
                *(pttyUSBHIDRxBuff+ttyDatCount) = ttyBitDat;
                ttyDatCount++;
                break;
            
            case 5: //接收总长数据
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {
                    stepStatus = 0;
                    break;
                }
                *(pttyUSBHIDRxBuff+ttyDatCount) = ttyBitDat;
                maxDatLen = ttyBitDat;
                ttyDatCount++;
                if(maxDatLen == 0) stepStatus = 7; //长度为0，直接接收校验位
                else  stepStatus = 6;
                break;

            case 6://按数据包中接收到指定长度的数据后，进入下一步接收校验位
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {
                    stepStatus = 0;
                    break;
                }
                *(pttyUSBHIDRxBuff+ttyDatCount) = ttyBitDat;
                ttyDatCount++;
                if(ttyDatCount > maxDatLen+4)  stepStatus = 7; // +4 补齐数据字节总长度(HEAD 2字节 + 地址码 + 命令码 + 长度，共4个字节）
                break;

            case 7: //接收校验位
                readFlag = read(pmsg->fd, &ttyBitDat, 1);
                if (readFlag <0) 
                {
                    stepStatus = 0;
                    break;
                }
                *(pttyUSBHIDRxBuff+ttyDatCount) = ttyBitDat;
                stepStatus = 8;
                break;

            case 8: //对数据进行校验，解析数据
                uint8_t checksum = 0;
                for(uint16_t ii=0; ii<ttyDatCount; ii++)
                { //计算除校验位以外的数据进行累加和
                    checksum += *(pttyUSBHIDRxBuff+ii);
                }

                if(checksum == *(pttyUSBHIDRxBuff+ttyDatCount)) 
                {
                    //数据校验正确
                    stepStatus = 0; //置位，重新接收新数据 
                    pmsg->len = ttyDatCount+1; 
                    // CP pttyUSBHIDRxBuff的数据到 pmsg->buff
                    for(uint16_t ii=0; ii<pmsg->len; ii++)
                    {
                        pmsg->buff[ii] = *(pttyUSBHIDRxBuff+ii);
                    }

                    time_t tim = time(NULL);
                    struct tm *tm = localtime(&tim);
                    struct timeval tv;
                    gettimeofday(&tv, NULL);   
                    printf("[%02d:%02d:%02d.%03ld] linux <<<<<-- CH9329 [USB HID, %d bytes] ",\
                    tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec/1000, ttyDatCount+1);
                    for(uint16_t ii=0; ii<=ttyDatCount; ii++)
                    { 
                        printf("%02x ", *(pttyUSBHIDRxBuff+ii));
                    }
                    printf("\n");


                    
                }else
                {
                    //数据校验不正确
                     printf("Notice: checksum error. data come from USB HID module.\n");
                     stepStatus = 0x00; //
                }
                break;

            default:
                stepStatus = 0x00;
                break;
       }
    }
  return msg;
}

